import math
import os
import numpy as np
# import matplotlib
# matplotlib.use('Agg')  # 切换到无 GUI 后端
import matplotlib.pyplot as plt
import pandas as pd
from datetime import datetime, timedelta
import matplotlib.dates as mdates

from PIL import Image

# 设置字体以支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题


class ShowFlowDiff:
    def __init__(self):
        self.path = ''
        self.data = {}
        self.p85 = None

    def read_file(self, path):
        self.path = path
        self.get_data()
        self.show_up_down()
        # self.show_up_down_diff()
        # self.show_up_down_rate()
        self.clear()

    def read_file_true(self, path, true_time_list):
        self.path = path
        self.get_data()
        self.show_up_down_true(true_time_list)
        self.show_up_down_diff_true(true_time_list)
        # self.show_up_down_rate()
        self.clear()

    def show(self):
        # 提取数据
        keys = list(self.data.keys())

        mean_speeds = [d['flow_diff'] for d in self.data.values() if 'flow_diff' in d]

        # 创建图形和坐标轴
        fig, ax = plt.subplots()
        # 绘制柱状图
        bar_width = 0.35
        indices = np.arange(len(keys))

        # 第一组柱状图
        # rects = ax.bar(indices, mean_speeds, bar_width, label='Mean Speed')
        ax.plot(indices, mean_speeds, marker='o', linestyle='-', color='r')
        # 绘制85分位数线
        plt.axhline(y=max(mean_speeds), color='b', linestyle='--')
        plt.axhline(y=min(mean_speeds), color='g', linestyle='--')

        plt.axhline(y=0, color='y', linestyle='--', label='0线')

        # 在柱子上添加数据标签
        def add_labels(rects):
            for rect in rects:
                height = rect.get_height()
                ax.annotate('{}'.format(height),
                            xy=(rect.get_x() + rect.get_width() / 2, height),
                            xytext=(0, 3),  # 3 points vertical offset
                            textcoords="offset points",
                            ha='center', va='bottom')

        # add_labels(rects1)
        # add_labels(rects2)

        # 设置 x 轴的刻度和标签，每隔12个显示一次
        ticks = indices[::12]  # 每隔12个索引选取一个
        tick_labels = keys[::12]  # 对应的标签也每隔12个选取一个


        # 添加标签和标题
        ax.set_xlabel('时间(小时)')
        ax.set_ylabel('流量差（辆）')
        ax.set_title('上下游门架流量差值统计')
        ax.set_xticks(ticks)
        ax.set_xticklabels(tick_labels)
        # ax.legend()

        # # 叠加折线图
        # diff = [d['flow_diff'] for d in data.values() if 'flow_diff' in d]
        # ax2 = ax.twinx()  # 创建第二个y轴
        # ax2.plot(indices, diff, marker='o', linestyle='-', color='r', label='Trend')
        # ax2.set_ylabel('Flow Diff')  # 我们假设这是趋势线的数据
        # ax2.legend(loc='upper right')

        # 显示图表
        plt.show()

    def show_up_down(self):
        # 提取数据
        keys = list(self.data.keys())
        # 将时间字符串转换为datetime对象
        times = [datetime.strptime(time, '%H:%M') for time in keys]
        up_flow = [d['up_flow'] for d in self.data.values() if 'up_flow' in d]
        down_flow = [d['down_flow'] for d in self.data.values() if 'down_flow' in d]

        plt.plot(times, up_flow,  marker=',', linestyle='-', color='r', label='上游流量')
        plt.plot(times, down_flow,  marker=',', linestyle='-', color='b', label='下游流量')

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        fig = ax.figure
        fig.set_size_inches(20, 12)  # 宽度为10英寸，高度为6英寸
        ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        # ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        if len(times) >= 10:
            start_time = times[10].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[10].replace(hour=23, minute=59, second=59, microsecond=999999)
        elif len(times) > 0:
            start_time = times[0].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[0].replace(hour=23, minute=59, second=59, microsecond=999999)
        else:
            start_time = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)
        ax.set_xlim(start_time, end_time)
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式

        # 添加标签和标题
        ax.set_xlabel('时间（小时）')
        ax.set_ylabel('流量（辆）')
        ax.set_title('上下游流量分布数据统计')
        ax.legend(loc='upper left')

        # # 叠加折线图
        # diff = [d['flow_diff'] for d in self.data.values() if 'flow_diff' in d]
        # ax2 = ax.twinx()  # 创建第二个y轴
        # ax2.plot(times, diff, marker='.', linestyle='-', color='y', label='Trend')
        # ax2.set_ylabel('Flow Diff')  # 我们假设这是趋势线的数据
        # ax2.legend(loc='upper right')

        # # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.path).split('.')[0]
        output_filename = os.path.join(output_dir, file_name + '.png')
        plt.savefig(output_filename, dpi=200)
        # 关闭图表以释放内存
        plt.close()

    def show_up_down_true(self, true_time_list):
        # 提取数据
        keys = list(self.data.keys())
        # 将时间字符串转换为datetime对象
        times = [datetime.strptime(time, '%H:%M') for time in keys]
        up_flow = [d['up_flow'] for d in self.data.values() if 'up_flow' in d]
        down_flow = [d['down_flow'] for d in self.data.values() if 'down_flow' in d]

        plt.plot(times, up_flow,  marker=',', linestyle='-', color='r', label='上游流量')
        plt.plot(times, down_flow,  marker=',', linestyle='-', color='b', label='下游流量')

        for i in range(len(true_time_list["true_value_list"])):
            x1_line = true_time_list["true_value_list"][i][:5]
            x_1 = datetime.strptime(x1_line, '%H:%M')
            plt.axvline(x=x_1, color='black', linestyle='--')
        for i in range(len(true_time_list["detection_value_list"])):
            x1_line = true_time_list["detection_value_list"][i]
            x_1 = datetime.strptime(x1_line, '%H:%M')
            plt.axvline(x=x_1, color='green', linestyle='--')

        ax = plt.gca()
        fig = ax.figure
        fig.set_size_inches(20, 12)
        ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        # 设置X轴时间范围固定为00:00到23:59
        if len(times) >= 10:
            start_time = times[10].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[10].replace(hour=23, minute=59, second=59, microsecond=999999)
        elif len(times) > 0:
            start_time = times[0].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[0].replace(hour=23, minute=59, second=59, microsecond=999999)
        else:
            start_time = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)
        ax.set_xlim(start_time, end_time)
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式
        # 可选：添加网格线以提高可读性
        plt.grid(True, which='both', linestyle='--', linewidth=0.5)

        # 添加标签和标题
        # ax.set_xlabel('时间（小时）')
        ax.set_ylabel('流量（辆）')
        ax.set_title('上下游流量分布数据统计')
        ax.legend(loc='upper left')

        # # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        # print(output_dir)
        file_name = os.path.basename(self.path).split('.')[0]
        output_filename = os.path.join(output_dir, file_name + '.png')
        plt.savefig(output_filename, dpi=200, bbox_inches='tight', transparent=False)
        # 关闭图表以释放内存
        plt.close()

    def show_up_down_diff(self):
        # 提取数据
        keys = list(self.data.keys())
        # 将时间字符串转换为datetime对象
        times = [datetime.strptime(time, '%H:%M') for time in keys]

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        fig = ax.figure
        fig.set_size_inches(20, 12)  # 宽度为10英寸，高度为6英寸
        ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        # ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        if len(times) >= 10:
            start_time = times[10].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[10].replace(hour=23, minute=59, second=59, microsecond=999999)
        elif len(times) > 0:
            start_time = times[0].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[0].replace(hour=23, minute=59, second=59, microsecond=999999)
        else:
            start_time = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)
        ax.set_xlim(start_time, end_time)
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式

        diff = [d['flow_diff'] for d in self.data.values() if 'flow_diff' in d]
        ax.plot(times, diff, marker='.', linestyle='-', color='y', label='Trend')
        ax.set_ylabel('Flow Diff')  # 我们假设这是趋势线的数据

        # 添加标签和标题
        ax.set_xlabel('时间（小时）')
        ax.set_ylabel('流量（辆）')
        ax.set_title('上下游10分钟时间差的流量差值统计')
        # ax.legend(loc='upper left')

        # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.path).split('.')[0]
        output_filename = os.path.join(output_dir, file_name + '.png')
        plt.savefig(output_filename, dpi=200)
        # 关闭图表以释放内存
        plt.close()

    def show_up_down_diff_true(self, true_time_list):
        # 提取数据
        keys = list(self.data.keys())
        # 将时间字符串转换为datetime对象
        times = [datetime.strptime(time, '%H:%M') for time in keys]
        diff = [d['flow_diff'] for d in self.data.values() if 'flow_diff' in d]
        plt.plot(times, diff, marker=',', linestyle='-', color='r', label='流量差')

        for i in range(len(true_time_list["true_value_list"])):
            x1_line = true_time_list["true_value_list"][i][:5]
            x_1 = datetime.strptime(x1_line, '%H:%M')
            plt.axvline(x=x_1, color='black', linestyle='--')
        for i in range(len(true_time_list["detection_value_list"])):
            x1_line = true_time_list["detection_value_list"][i]
            x_1 = datetime.strptime(x1_line, '%H:%M')
            plt.axvline(x=x_1, color='green', linestyle='--')

        ax = plt.gca()
        fig = ax.figure
        fig.set_size_inches(20, 12)
        ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        # 设置X轴时间范围固定为00:00到23:59
        if len(times) >= 10:
            start_time = times[10].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[10].replace(hour=23, minute=59, second=59, microsecond=999999)
        elif len(times) > 0:
            start_time = times[0].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[0].replace(hour=23, minute=59, second=59, microsecond=999999)
        else:
            start_time = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)
        ax.set_xlim(start_time, end_time)
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式
        # 可选：添加网格线以提高可读性
        plt.grid(True, which='both', linestyle='--', linewidth=0.5)

        # 添加标签和标题
        # ax.set_xlabel('时间（小时）')
        ax.set_ylabel('流量（辆）')
        ax.set_title('上下游门架流量差值统计')

        # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.path).split('.')[0] + "_diff"
        output_filename = os.path.join(output_dir, file_name + '.png')
        plt.savefig(output_filename, dpi=200, bbox_inches='tight', transparent=False)
        # 关闭图表以释放内存
        plt.close()

    def show_up_down_rate(self):
        # 提取数据
        keys = list(self.data.keys())
        # 将时间字符串转换为datetime对象
        times = [datetime.strptime(time, '%H:%M') for time in keys]

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        fig = ax.figure
        fig.set_size_inches(20, 12)  # 宽度为10英寸，高度为6英寸
        ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        # ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式

        diff = [d['rate'] for d in self.data.values() if 'rate' in d]
        ax.plot(times, diff, marker='.', linestyle='-', color='g', label='Trend')
        ax.set_ylabel('Flow Diff')  # 我们假设这是趋势线的数据

        # 添加标签和标题
        ax.set_xlabel('时间（小时）')
        ax.set_ylabel('流量（辆）')
        ax.set_title('上下游10分钟时间差的通行率统计')
        # ax.legend(loc='upper left')

        # # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.path).split('.')[0]
        output_filename = os.path.join(output_dir, file_name + '.png')
        plt.savefig(output_filename, dpi=200)
        # 关闭图表以释放内存
        plt.close()

    def get_data(self):
        df_up = pd.read_csv(self.path)
        data0 = df_up.to_dict(orient='records')
        # print(data0)
        self.data = {}
        for i in range(2, len(data0)):
            time = data0[i]['time'].split(' ')[1][:5]
            self.data[time] = {
                "total_flow": data0[i]['total_flow'],
                "up_flow": data0[i]['up_flow'],
                "down_flow": data0[i]['down_flow'],
                "flow_diff": data0[i]['up_flow'] - data0[i]['down_flow'],
                "rate": data0[i]['down_flow'] / data0[i]['up_flow'] if data0[i]['up_flow'] != 0 else 0,
                "rate2": int((data0[i]['up_flow'] - data0[i]['down_flow']) / data0[i]['up_flow'] * 100) if data0[i]['up_flow'] != 0 else 0,
            }
        # print(self.data)

    def clear(self):
        self.data.clear()
        self.p85 = None
        self.path = ''


if __name__ == '__main__':

    name = "G004251002000620010,G004251001000320010-20240404"
    path0 = r'D:\GJ\项目\事故检测\output\邻垫高速'
    path = os.path.join(path0, name, 'mate_flow_data.csv')

    showFlowDiff = ShowFlowDiff()
    showFlowDiff.read_file(path)

